package handler;

import enums.MessageType;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import protocol.Header;
import protocol.NettyMessage;

public class LoginAuthRespHandler extends ChannelInboundHandlerAdapter {

  private Map<String,Boolean> nodeCheck = new ConcurrentHashMap<String, Boolean>();

  private String[] whitekList = {"127.0.0.1"};

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println("登录器连接成功"+System.currentTimeMillis());
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    //如果是握手请求消息,处理,其他消息透传
    System.out.println("开始登录处理");
    NettyMessage message = (NettyMessage) msg;
    if (message.getHeader().getType() == MessageType.LOGIN_REQ.value()){
      String nodeIndex = ctx.channel().remoteAddress().toString();
      NettyMessage loginResp = null;
      //重复连接,拒绝
      if(nodeCheck.containsKey(nodeIndex)){
        loginResp = buildResponse((byte) -1);
      }
      //认证是否在白名单中
      else {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.getAddress().getHostAddress();
        boolean isOk = false;
        for (String wip : whitekList){
          if (wip.equals(ip)){
            isOk = true;
            break;
          }
        }
        loginResp = isOk ? buildResponse((byte) 0) : buildResponse((byte) -1);
        //认证成功后写入登陆保护
        if (isOk){
          nodeCheck.put(nodeIndex,true);
        }
        System.out.println("the login response is :"+loginResp+" body ["
           + loginResp.getBody() + "]");
        //返回握手信息
        ctx.writeAndFlush(loginResp);
      }
    }else{
      //消息透传
      ctx.fireChannelRead(msg);
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    //链路发生异常时,清除登录保护
    nodeCheck.remove(ctx.channel().remoteAddress().toString());
    ctx.close();
    cause.printStackTrace();
  }

  private NettyMessage buildResponse(byte result){
    NettyMessage message = new NettyMessage();
    Header header = new Header();
    header.setType(MessageType.LOGIN_RESP.value());
    message.setHeader(header);
    message.setBody(result);
    return message;
  }

}
